﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Auxiliaries
{
    /// <summary>
    /// Hexadecimal converter
    /// </summary>
    public static class HEX_converter
    {
        static char[] hexDigits = {
        '0', '1', '2', '3', '4', '5', '6', '7',
        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

        /// <summary>
        /// Converts to a single line string
        /// </summary>
        public static string ToHexString(byte[] bytes)
        {
            char[] chars = new char[bytes.Length * 2];
            for (int i = 0; i < bytes.Length; i++)
            {
                int b = bytes[i];
                chars[i * 2] = hexDigits[b >> 4];
                chars[i * 2 + 1] = hexDigits[b & 0xF];
            }
            return new string(chars);
        }

        /// <summary>
        /// Converts to a single line string
        /// </summary>
        public static string ToHexString(Int64 valInt)
        {
            byte[] valByte = new byte[4];
            for (int k = 0; k < 4; k++)
                valByte[3 - k] = (byte)(valInt >> 8 * k);

            return ToHexString(valByte);
        }

        /// <summary>
        /// Converts to a single line string with 2 charecters separation
        /// </summary>
        public static string ToHexStringSpaced(byte[] bytes)
        {
            char[] chars = new char[bytes.Length * 4];
            for (int i = 0; i < bytes.Length; i++)
            {
                int b = bytes[i];
                chars[i * 4] = hexDigits[b >> 4];
                chars[i * 4 + 1] = hexDigits[b & 0xF];
                chars[i * 4 + 2] = ' ';
                chars[i * 4 + 3] = ' ';
            }
            return new string(chars);
        }

        /// <summary>
        /// Converts a hex string representation to an unsigned 64 bit integer value
        /// </summary>
        /// <param name="hexed">The hex string representation to convert</param>
        /// <param name="convert">A 64 bit unsigned integer value derived from the string</param>
        /// <returns>True if operation is successful</returns>
        public static bool ToBinary(string hexed, out UInt64 convert)
        {
            convert = 0;
            if (hexed.Substring(0, 2) == "0x")
                hexed = hexed.Substring(2, hexed.Length - 2);
            if ((hexed.Length % 2) != 0)
                hexed = "0" + hexed;
            for (int i = 0; i < hexed.Length; i++)
            {
                convert = (UInt64)convert << 8;
                byte tmp = 0;
                for (int bi = 0; bi < 2; bi++)
                {
                    tmp = (byte)(tmp << 4);
                    switch (hexed[i])
                    {
                        case '0':
                            tmp |= 0x0;
                            break;
                        case '1':
                            tmp |= 0x1;
                            break;
                        case '2':
                            tmp |= 0x2;
                            break;
                        case '3':
                            tmp |= 0x3;
                            break;
                        case '4':
                            tmp |= 0x4;
                            break;
                        case '5':
                            tmp |= 0x5;
                            break;
                        case '6':
                            tmp |= 0x6;
                            break;
                        case '7':
                            tmp |= 0x7;
                            break;
                        case '8':
                            tmp |= 0x8;
                            break;
                        case '9':
                            tmp |= 0x9;
                            break;
                        case 'A':
                        case 'a':
                            tmp |= 0xA;
                            break;
                        case 'B':
                        case 'b':
                            tmp |= 0xB;
                            break;
                        case 'C':
                        case 'c':
                            tmp |= 0xC;
                            break;
                        case 'D':
                        case 'd':
                            tmp |= 0xD;
                            break;
                        case 'E':
                        case 'e':
                            tmp |= 0xE;
                            break;
                        case 'F':
                        case 'f':
                            tmp |= 0xF;
                            break;
                        default:
                            return false;
                    }
                    if (!(i < hexed.Length - 1))
                        bi = 2;
                    else if (bi < 1)
                        i++;
                }
                convert += (UInt64)tmp;
            }
            return true;
        }
    }
}